home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / LISTINGS / V_13_04 / CHAPMAN.ZIP / COMPLAIN.CPP < prev    next >
Encoding:
Text File  |  1994-03-02  |  6.9 KB  |  234 lines

  1. Listing 9.
  2.  
  3. /* complain.cpp - message dictionary manager */
  4.  
  5. #include <stdio.h>
  6. #ifdef __ZTC__
  7. #include <io.h>                 /* fseek() */
  8. #endif
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "utils.hpp"
  12. #include "errmgr.hpp"
  13. #include "complain.hpp"
  14.  
  15. /* a singly linked list of keys - should use hash */
  16. /* table for speed */
  17. class complain_ptr {
  18.     public:
  19.         complain_ptr(char *name,long offset,
  20.                      complain_ptr *head);
  21.         ~complain_ptr(void);
  22.         const char *errname(void) const
  23.             { return _errname; }
  24.         int complaint_text(const char *filename,
  25.                            char *line,int linelen);
  26.         complain_ptr *next;
  27.     private:
  28.         char *_errname;
  29.         long foffset;
  30. };
  31.  
  32. /*************** class complaint_dict ***************/
  33.  
  34. static complain_ptr *read_complaint_file(
  35.                          const char *filename);
  36.  
  37. complaint_dict::complaint_dict(const char *filename)
  38. {
  39.     /* constructor - remember file name, read all */
  40.     /* messages and store offsets */
  41.     _filename = newstring(filename);
  42.     complain_table = read_complaint_file(_filename);
  43. }
  44.  
  45. complaint_dict::~complaint_dict(void)
  46. {
  47.     /* cleanup - delete all of the offset records */
  48.     /* in the table. */
  49.     complain_ptr *keyptr;
  50.  
  51.     free(_filename);
  52.     while ((keyptr = complain_table) != 0) {
  53.         complain_table = complain_table->next;
  54.         delete keyptr;
  55.     }
  56. }
  57.  
  58. static complain_ptr *key(complain_ptr *complain_table,
  59.                          const char *name)
  60. {
  61.     /* look for the key in the list of complain_ptr */
  62.     /* objects. returns 0 if not found. */
  63.     while (complain_table != 0 &&
  64.            strcmp(name,complain_table->errname()))
  65.         complain_table = complain_table->next;
  66.     return complain_table;
  67. }
  68.  
  69. int complaint_dict::key_defined(const char *name) const
  70. {
  71.     /* return 1 if the key is defined here. */
  72.     return key(complain_table,name) != 0;
  73. }
  74.  
  75. int complaint_dict::complaint_text(const char *name,
  76.                                    char *line,
  77.                                    int linelen) const
  78. {
  79.     /* retrieve the text for the named message and */
  80.     /* store it in the buffer. returns 0 on failure. */
  81.     complain_ptr *fmt;
  82.  
  83.     fmt = key(complain_table,name);
  84.     if (fmt == 0) {
  85.         sprintf(line,"Error key \"%s\" not found\n",
  86.                 key);
  87.         return 0;               /* failed */
  88.     }
  89.     if (fmt->complaint_text(_filename,line,linelen)) {
  90.         sprintf(line,"Unable to re-read text for "
  91.                 "error key \"%s\"\n",key);
  92.         return 0;               /* failed */
  93.     }
  94.     return 1;                   /* all OK */
  95.  
  96. }  /* end of complaint_dict::complaint_text() */
  97.  
  98. /************** local utility routines **************/
  99.  
  100. static complain_ptr *read_complaint_file(
  101.                           const char *filename)
  102. {
  103.     /* read all of the error keys in the complaint */
  104.     /* file. */
  105.     FILE *complaintfile;
  106.     char line[512];
  107.     long thisoffset;
  108.     char *keyname,*p,*name;
  109.     int all_ok = 1;
  110.     complain_ptr *keyptr,*complain_table = 0;
  111.  
  112.     if ((complaintfile = fopen(filename,"r")) == 0) {
  113.         err_mgr.error("Unable to read error text "
  114.                       "file %s\n",filename);
  115.         return 0;               /* OK to continue */
  116.     }
  117.  
  118.     for (;;) {                  /* exit from within */
  119.         /* remember the start of each line. */
  120.         thisoffset = ftell(complaintfile);
  121.         read_continued_line(complaintfile,line,
  122.                             sizeof(line));
  123.         if (strlen(line) == 0)  /* EOF? done */
  124.             break;
  125.  
  126.         /* skip blank lines and comments. */
  127.         keyname = p = line + skipblanks(line);
  128.         if (!*p || *p == '\n' || *p == '#')
  129.             continue;
  130.         p += skip_ident(p);     /* get key name */
  131.         if (p == keyname) {
  132.             err_mgr.warn("Missing error key in error "
  133.                          text file \"%s\":\n%s",
  134.                          filename,line);
  135.             all_ok = 0;
  136.             continue;
  137.         }
  138.  
  139.         name = newstring(keyname,p - keyname);
  140.         if (key(complain_table,name) != 0) {
  141.             err_mgr.warn("Duplicate error key in "
  142.                          "error text file \"%s\":\n%s",
  143.                          filename,line);
  144.             free(name);
  145.             all_ok = 0;
  146.             continue;
  147.         }
  148.         p += skipblanks(p);
  149.         if (*p != ':') {
  150.             err_mgr.warn("Missing ':' in error text "
  151.                          "file \"%s\":\n%s",
  152.                          filename,line);
  153.             free(name);
  154.             all_ok = 0;
  155.             continue;
  156.         }
  157.  
  158.         /* everything looks good - remember key. */
  159.         keyptr = new complain_ptr(name,thisoffset,
  160.                                   complain_table);
  161.         complain_table = keyptr;
  162.     }
  163.  
  164.     /* if problems were found ignore entire file. */
  165.     fclose(complaintfile);
  166.     if (!all_ok) {
  167.         while ((keyptr = complain_table) != 0) {
  168.             complain_table = complain_table->next;
  169.             delete keyptr;
  170.         }
  171.         return 0;
  172.     }
  173.     return complain_table;
  174. }
  175.  
  176. /**************** class complain_ptr ****************/
  177.  
  178. complain_ptr::complain_ptr(char *name,long offset,
  179.                            complain_ptr *head)
  180. {                               /* constructor */
  181.     /* add the new complain_ptr to the front of */
  182.     /* the list. name is allocated for us; the */
  183.     /* destructor must free it. */
  184.     _errname = name;
  185.     foffset = offset;
  186.     next = head;
  187. }
  188.  
  189. complain_ptr::~complain_ptr(void)  /* destructor */
  190. {
  191.     /* our caller cleans up the chain in next. */
  192.     free(_errname);
  193. }
  194.  
  195. int complain_ptr::complaint_text(
  196.                       const char *filename,
  197.                       char *line,int linelen)
  198. {
  199.     /* re-read the message text for the key. */
  200.     /* returns 1 on error (file has disappeared or */
  201.     /* been edited). */
  202.     FILE *complaintfile;
  203.     char *keyname,*p;
  204.     int newlen;
  205.  
  206.     line[0] = '\0';             /* clear old text */
  207.     if ((complaintfile = fopen(filename,"r")) == 0)
  208.         return 1;
  209.     if (fseek(complaintfile,foffset,SEEK_SET)) {
  210.         fclose(complaintfile);
  211.         return 1;
  212.     }
  213.     read_continued_line(complaintfile,line,linelen);
  214.     fclose(complaintfile);
  215.  
  216.     /* make sure we still have the same key! (file */
  217.     /* may have been edited) */
  218.     keyname = p = line + skipblanks(line);
  219.     p += skip_ident(p);
  220.     if (p == keyname ||
  221.         strncmp(keyname,_errname,strlen(_errname)))
  222.         return 1;
  223.     p += skipblanks(p);
  224.     if (*p != ':')
  225.         return 1;
  226.     ++p;                        /* skip ':', */
  227.     p += skipblanks(p);         /* leading blanks */
  228.  
  229.     /* shift everything over to cover the key. */
  230.     newlen = strlen(p);
  231.     memmove(line,p,newlen + 1);
  232.     return 0;                   /* all OK */
  233. }
  234.